using System.Collections;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace PropertyExpression.ControllableQuery.Demo
{
    public static class SqlCommandExtensions
    {
        public static IQuery2<T> Query<T>(this SqlCommand command)
        {
            return command.Query<T>(DALTest.ConnectionString);
        }

        public static IQuery2<T> Query<T>(this SqlCommand command, string connectionString)
        {
            return new QueryImpl<T>(command, connectionString);
        }

        private class QueryImpl<T>: IQuery2<T>
        {
            private readonly SqlCommand sqlCommand;
            private readonly string connectionString;
            private readonly IEnumerable<T> enumerable;

            public QueryImpl(SqlCommand sqlCommand, string connectionString)
            {
                this.sqlCommand = sqlCommand;
                this.connectionString = connectionString;
                enumerable = GetEnumerable<T>(sqlCommand, connectionString);
            }

            public IEnumerator<T> GetEnumerator()
            {
                return enumerable.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

            public SqlCommand SqlCommand
            {
                get { return sqlCommand; }
            }

            public string ConnectionString
            {
                get { return connectionString; }
            }
        }

        private static IEnumerable<T> GetEnumerable<T>(SqlCommand command, string connectionString)
        {
            using (var connection = new SqlConnection(connectionString))
            {
                connection.Open();
                command.Connection = connection;
                using (var reader = command.ExecuteReader())
                    while (reader.Read())
                        yield return reader.Materialize<T>();
            }
        }
    }

    public interface IQuery2<out T>: IEnumerable<T>
    {
        SqlCommand SqlCommand { get; }
        string ConnectionString { get; }
    }
}